home *** CD-ROM | disk | FTP | other *** search
/ QuickTime 2.0 Beta / Quicktime 2.0 Beta.iso / Programming Stuff / Sample Code / DTS Sample Code / MyCaptureApp ƒ 1.0b4 / MySGStuff.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-04-28  |  26.1 KB  |  980 lines  |  [TEXT/KAHL]

  1. /*
  2.     File:        MySGStuff.c
  3.     
  4.     Contains:    Sequence grabber code.
  5.  
  6.     Written by:    John Wang
  7.  
  8.     Copyright:    © 1994 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.  
  12.         <4>        04/25/94    JW        1.0b4.  Fixed minor bug in 1.0b3 where if the sound channel wasn't
  13.                                     opened, then MyUpdateChannels would fail.
  14.         <3>        04/18/94    JW        1.0b3.  Support for multiple capture channels.
  15.         <2>        04/08/94    JW        1.0b2.  Support for preferences file added so that channel
  16.                                     settings is preserved.
  17.         <1>        04/04/94    JW        Started and created as 1.0b1.
  18.  
  19.     To Do:
  20.     
  21. */
  22.  
  23. #ifdef THINK_C
  24. #define        applec
  25. #endif
  26.  
  27. #include    "MyHeaders"
  28. /*
  29. #include    <Types.h>
  30. #include    <Memory.h>
  31. #include    <QuickDraw.h>
  32. #include    <Palettes.h>
  33. #include    <QDOffscreen.h>
  34. #include    <Errors.h>
  35. #include    <Fonts.h>
  36. #include    <Dialogs.h>
  37. #include    <Windows.h>
  38. #include    <Menus.h>
  39. #include    <Events.h>
  40. #include    <Desk.h>
  41. #include    <DiskInit.h>
  42. #include    <OSUtils.h>
  43. #include    <Resources.h>
  44. #include    <ToolUtils.h>
  45. #include    <AppleEvents.h>
  46. #include    <EPPC.h>
  47. #include    <GestaltEqu.h>
  48. #include    <Processes.h>
  49. #include    <Balloons.h>
  50. #include    <Aliases.h>
  51. #include    <MixedMode.h>
  52. #include    <Scrap.h>
  53. #include    <LowMem.h>
  54.  
  55. #include    <Movies.h>
  56. #include    <QuickTimeComponents.h>
  57. */
  58.  
  59. #include    "MyCaptureAppShell.h"
  60. #include    "MySGStuff.h"
  61. #include    "MyUtils.h"
  62.  
  63. /* ------------------------------------------------------------------------- */
  64.  
  65. //    Contains application runtime variables.  Stored in window refCon as handle block.
  66. struct WindowInfo {
  67.     ComponentInstance        theSG;
  68.     SGChannel                channel[kMAXCHANNELS];
  69.     Boolean                    recordPlayThru;
  70.     Boolean                    createSeparateFiles;
  71. };
  72. typedef        struct WindowInfo WindowInfo, *WindowInfoPtr, **WindowInfoHandle;
  73.  
  74. //    Contains compression settings for the video channel.  Used in SGInfo.
  75. struct CompressionInfo {
  76.     OSType        compressorType;
  77.     short        depth;
  78.     CodecQ        spatialQuality;
  79.     CodecQ        temporalQuality;
  80.     long        keyFrameRate;
  81. };
  82. typedef        struct CompressionInfo CompressionInfo;
  83.  
  84. //    Contains Sequence Grabber channel information.  Stored as a global variable.
  85. struct SGInfo {
  86.     CompressionInfo        cInfo;
  87.     OSType                channelType[kMAXCHANNELS];
  88.     Handle                channelName[kMAXCHANNELS];
  89.     UserData            channelSettings[kMAXCHANNELS];
  90. };
  91. typedef        struct SGInfo SGInfo;
  92. SGInfo        gSGInfo;
  93.  
  94. //    Boolean variable.  true is QuickTime 2.0 or later.  false otherwise i.e. 1.6.2.
  95. Boolean        gHasQuickTime20;
  96.  
  97. /* ------------------------------------------------------------------------- */
  98.  
  99. //    MyInitialize is called at init time after the toolbox is initialized.  This routine is
  100. //    called only once.
  101.  
  102. long MyInitialize()
  103. {
  104.     long                    err;
  105.     long                    QDfeature;
  106.     short                    myRefNum;
  107.     short                    i;
  108.     ComponentDescription    cd, theCD;
  109.     Component                aComponent;
  110.     Boolean                    done;
  111.     MenuHandle                mHandle;
  112.     
  113.     //    We require QuickTime so make sure it is available.
  114.     err = Gestalt(gestaltQuickTime, &QDfeature);
  115.     if ( err != noErr )
  116.         return ( err );
  117.         
  118.     //    Check for QuickTime 2.0 or later.
  119.     gHasQuickTime20 = ((QDfeature >> 16) & 0xffff) >= 0x200;
  120.     
  121.     //    Start the engine.
  122.     err = EnterMovies();
  123.     if ( err != noErr )
  124.         return ( err) ;
  125.     
  126.     //    Find out what sequence grabber channels are available by searching all sequence
  127.     //    grabber channel components.  Get channelType[] and channelName[].
  128.     for ( i=0; i<kMAXCHANNELS; i++ ) {
  129.         gSGInfo.channelType[i] = 0;
  130.         gSGInfo.channelName[i] = nil;
  131.     }
  132.     cd.componentType = SeqGrabChannelType;
  133.     cd.componentSubType = 0;
  134.     cd.componentManufacturer = 0;
  135.     cd.componentFlags = 0;
  136.     cd.componentFlagsMask = 0;
  137.     aComponent = 0;
  138.     for ( i=0, done=false; i<kMAXCHANNELS && !done; i++ ) {
  139.         aComponent = FindNextComponent(aComponent, &cd);
  140.         if (aComponent != 0) {
  141.             gSGInfo.channelName[i] = NewHandle(4);
  142.             GetComponentInfo(aComponent, &theCD, gSGInfo.channelName[i], nil, nil);
  143.             gSGInfo.channelType[i] = theCD.componentSubType;
  144.         } else
  145.             done = true;
  146.     }
  147.  
  148.     //    Read preferences for compression settings and
  149.     //    channelSettings[] (if channel has been previously found).
  150.     if ( (myRefNum = readPreferencesFile()) != -1 ) {
  151.         //    File opened.
  152.         Handle            myHandle;
  153.  
  154.         //    Get Compression info.
  155.         myHandle = Get1Resource('INFO', 128);
  156.         if ( myHandle != nil ) {
  157.             DetachResource(myHandle);
  158.             HLock(myHandle);
  159.             BlockMove(*myHandle, &(gSGInfo.cInfo), sizeof(CompressionInfo));
  160.             HUnlock(myHandle);
  161.             DisposeHandle(myHandle);
  162.         } else {
  163.             //    If no such resource, then manually udpate the values.
  164.             gSGInfo.cInfo.compressorType = 'raw ';
  165.             gSGInfo.cInfo.depth = 16;
  166.             gSGInfo.cInfo.spatialQuality = codecLosslessQuality;
  167.             gSGInfo.cInfo.temporalQuality = 0;
  168.             gSGInfo.cInfo.keyFrameRate = 0;
  169.         }
  170.         
  171.         //    Get all the saved channel settings for the channels that are available.
  172.         for ( i=0; i< kMAXCHANNELS; i++ ) {
  173.             if (gSGInfo.channelType[i] != 0) {
  174.                 myHandle = Get1Resource(gSGInfo.channelType[i], 128);
  175.                 if ( myHandle != nil ) {
  176.                     err = NewUserDataFromHandle(myHandle, &(gSGInfo.channelSettings[i]));
  177.                     if ( err != noErr ) {
  178.                         ReportWarning("\pCould not create user data from handle: ", err);
  179.                         gSGInfo.channelSettings[i] = nil;
  180.                     }
  181.                 } else
  182.                     gSGInfo.channelSettings[i] = nil;
  183.             } else
  184.                 gSGInfo.channelSettings[i] = nil;
  185.         }
  186.         
  187.         //    Finished.  Close the preferences file.
  188.         closePreferencesFile(myRefNum);
  189.     } else {
  190.         //    If no preferences file, then use default values.
  191.         gSGInfo.cInfo.compressorType = 'raw ';
  192.         gSGInfo.cInfo.depth = 16;
  193.         gSGInfo.cInfo.spatialQuality = codecLosslessQuality;
  194.         gSGInfo.cInfo.temporalQuality = 0;
  195.         gSGInfo.cInfo.keyFrameRate = 0;
  196.         for ( i=0; i< kMAXCHANNELS; i++ )
  197.             gSGInfo.channelSettings[i] = nil;
  198.     }
  199.  
  200.     //    Add the channel names to the menu.
  201.     mHandle = GetMHandle(kMENU_SETTINGSID);
  202.     for ( i=0; i<kMAXCHANNELS; i++ ) {
  203.         if (gSGInfo.channelType[i] != 0) {
  204.             Str255        myStr;
  205.             
  206.             BlockMove("   Disable", &myStr[1], 11);
  207.             BlockMove(*(gSGInfo.channelName[i]), &myStr[11], **(gSGInfo.channelName[i]) + 1);
  208.             myStr[0] = 11 + **(gSGInfo.channelName[0]);
  209.             myStr[11] = ' ';
  210.             AppendMenu(mHandle, (unsigned char *) *(gSGInfo.channelName[i]));
  211.             AppendMenu(mHandle, myStr);
  212.         }
  213.     }
  214.  
  215.     return ( noErr );
  216. }
  217.  
  218. void MyFinishup()
  219. {
  220.     long                err;
  221.     short                myRefNum, i;
  222.     
  223.     //    Should close all windows.  But, since we know this app only supports one window, we
  224.     //    don't need to loop.
  225.     MyClose();
  226.  
  227.     //    Write preferences file for all channel settings and compression settings.
  228.     if ((myRefNum = writePreferencesFile()) != -1) {
  229.         Handle            mySetting, myInfo;
  230.         
  231.         //    Write the compressor settings to preferences file.
  232.         myInfo = NewHandle(sizeof(CompressionInfo));
  233.         if ( myInfo == nil ) {
  234.             ReportWarning("\pCound not create compressor settings handle.", 0);
  235.         } else {
  236.             HLock((Handle) myInfo);
  237.             BlockMove(&(gSGInfo.cInfo), *myInfo, sizeof(CompressionInfo));
  238.             HUnlock((Handle) myInfo);
  239.             AddResource(myInfo, 'INFO', 128, "\pCompression Settings.");
  240.         }
  241.         
  242.         //    Write out channel settings.
  243.         for ( i=0; i< kMAXCHANNELS; i++ ) {
  244.             if (gSGInfo.channelType[i] != 0 && gSGInfo.channelSettings[i] != nil ) {
  245.                 mySetting = NewHandle(4);
  246.                 if ( mySetting == nil ) {
  247.                     ReportWarning("\pCound not create settings handle.", 0);
  248.                 } else {
  249.                     PutUserDataIntoHandle(gSGInfo.channelSettings[i], mySetting);
  250.                     AddResource(mySetting, gSGInfo.channelType[i], 128, "\pSettings.");
  251.                 }
  252.             } else
  253.                 gSGInfo.channelSettings[i] = nil;
  254.         }
  255.         
  256.         closePreferencesFile(myRefNum);
  257.     } else
  258.         ReportWarning("\pSorry.  Could not create preferences file.", 0);
  259. }
  260.  
  261. void MyIdle()
  262. {
  263.     WindowPtr        theWindow;
  264.  
  265.     theWindow = FrontWindow();
  266.     
  267.     //    Only one window allowed to be opened at a time.
  268.     if ( theWindow != nil ) {    //    Yes, window open.
  269.         WindowInfoHandle    myWindowInfo;
  270.         
  271.         myWindowInfo = (WindowInfoHandle) GetWRefCon(theWindow);
  272.         if ((**myWindowInfo).theSG != nil)
  273.             SGIdle((**myWindowInfo).theSG);
  274.     }
  275. }
  276.  
  277. long MyYieldTime(long message)
  278. {
  279.     if ( message )
  280.         //    Resume message
  281.         return ( 0 );
  282.     else
  283.         //    Suspend message
  284.         return ( 30 );
  285. }
  286.  
  287. void MyAdjustMenus()
  288. {
  289.     MenuHandle            mHandle;
  290.     WindowPtr            theWindow;
  291.     WindowInfoHandle    myWindowInfo;
  292.     short                 i;
  293.     
  294.     theWindow = FrontWindow();
  295.     
  296.     myWindowInfo = (WindowInfoHandle) GetWRefCon(theWindow);
  297.  
  298.     //    Allow only one window to be opened.
  299.     if ( theWindow != nil ) {    //    Yes, window open.
  300.         //    File menu.
  301.         mHandle = GetMHandle(kMENU_FILEID);
  302.         DisableItem(mHandle, kMENU_FILENEW);
  303.         EnableItem(mHandle, kMENU_FILECLOSE);
  304.         
  305.         //    Settings menu.
  306.         mHandle = GetMHandle(kMENU_SETTINGSID);
  307.         EnableItem(mHandle, 0);
  308.         for ( i=0; i<kMAXCHANNELS; i++ ) {
  309.             if (gSGInfo.channelType[i] != 0) {
  310.                 if ( (**myWindowInfo).channel[i] != nil ) {
  311.                     EnableItem(mHandle, i*2+1);
  312.                     EnableItem(mHandle, i*2+2);
  313.                 } else {
  314.                     DisableItem(mHandle, i*2+1);
  315.                     DisableItem(mHandle, i*2+2);
  316.                 }
  317.             }
  318.         }
  319.  
  320.         //    Resize menu.
  321.         mHandle = GetMHandle(kMENU_RESIZEID);
  322.         EnableItem(mHandle, 0);
  323.  
  324.         //    Special menu.
  325.         mHandle = GetMHandle(kMENU_SPECIALID);
  326.         EnableItem(mHandle, 0);
  327.         CheckItem(mHandle, kMENU_SPECIALPLAYTHRU, (**myWindowInfo).recordPlayThru);
  328.         if ( !gHasQuickTime20 ) {
  329.             (**myWindowInfo).createSeparateFiles = false;
  330.             DisableItem(mHandle, kMENU_SPECIALSEPARATEFILES);
  331.         } else
  332.             EnableItem(mHandle, kMENU_SPECIALSEPARATEFILES);
  333.         CheckItem(mHandle, kMENU_SPECIALSEPARATEFILES, (**myWindowInfo).createSeparateFiles);
  334.     
  335.         //    Record menu.
  336.         mHandle = GetMHandle(kMENU_RECORDID);
  337.         EnableItem(mHandle, 0);
  338.  
  339.     } else {    //    No window open.
  340.         //    File menu.
  341.         mHandle = GetMHandle(kMENU_FILEID);
  342.         EnableItem(mHandle, kMENU_FILENEW);
  343.         DisableItem(mHandle, kMENU_FILECLOSE);
  344.  
  345.         //    Settings menu.
  346.         mHandle = GetMHandle(kMENU_SETTINGSID);
  347.         DisableItem(mHandle, 0);
  348.         for ( i=0; i<kMAXCHANNELS; i++ ) {
  349.             if (gSGInfo.channelType[i] != 0) {
  350.                 EnableItem(mHandle, i*2);
  351.                 EnableItem(mHandle, i*2+1);
  352.             }
  353.         }
  354.  
  355.         //    Resize menu.
  356.         mHandle = GetMHandle(kMENU_RESIZEID);
  357.         DisableItem(mHandle, 0);
  358.  
  359.         //    Special menu.
  360.         mHandle = GetMHandle(kMENU_SPECIALID);
  361.         DisableItem(mHandle, 0);
  362.         CheckItem(mHandle, kMENU_SPECIALPLAYTHRU, false);
  363.         CheckItem(mHandle, kMENU_SPECIALSEPARATEFILES, false);
  364.  
  365.         //    Record menu.
  366.         mHandle = GetMHandle(kMENU_RECORDID);
  367.         DisableItem(mHandle, 0);
  368.     }
  369.     
  370.     DrawMenuBar();
  371. }
  372.  
  373. /* ------------------------------------------------------------------------- */
  374.  
  375. void MyNew()
  376. {
  377.     long                    err;
  378.     WindowPtr                myWindow;
  379.     Rect                    myBounds = {42, 4, 282, 324};
  380.     WindowInfoHandle        myWindowInfo;
  381.     short                    i, videoChannel, soundChannel;
  382.     
  383.     myWindow = nil;
  384.     myWindowInfo = nil;
  385.     
  386.     //    Create window along with window info record.
  387.     myWindow = NewCWindow(0L, &myBounds, "\pCapture window", 1, documentProc, (WindowPtr) -1, true, 0L);
  388.     if (myWindow == nil) {
  389.         ReportWarning("\pCould not create new window.",0);
  390.         goto bail;
  391.     }
  392.     SetGWorld((CGrafPtr) myWindow, GetMainDevice());
  393.     myWindowInfo = (WindowInfoHandle) NewHandleClear(sizeof(WindowInfo));
  394.     if ( myWindowInfo == nil ) {
  395.         ReportWarning("\pCould not create window info handle.", 0);
  396.         goto bail;
  397.     }
  398.     MoveHHi((Handle) myWindowInfo);
  399.     HLock((Handle) myWindowInfo);
  400.     SetWRefCon(myWindow, (long) myWindowInfo);
  401.     (**myWindowInfo).recordPlayThru = false;
  402.     (**myWindowInfo).createSeparateFiles = false;
  403.     
  404.     //    Open sequence grabber and initialize the sequence grabber.
  405.     (**myWindowInfo).theSG = OpenDefaultComponent(SeqGrabComponentType, 0);
  406.     if ( (**myWindowInfo).theSG == nil) {
  407.         ReportWarning("\pOpenDefaultComponent failed to open default sequence grabber component.", 0);
  408.         goto bail;
  409.     }
  410.     err = SGInitialize((**myWindowInfo).theSG);
  411.     if ( err != noErr ) {
  412.         ReportWarning("\pCould not initialize sequence grabber: ", err);
  413.         goto bail;
  414.     }
  415.     
  416.     //    First things first, set the GWorld to the newly created window.
  417.     err = SGSetGWorld((**myWindowInfo).theSG, (CGrafPtr) myWindow, GetMainDevice());
  418.     if ( err != noErr ) {
  419.         ReportWarning("\pCould not SGSetGWorld: ", err);
  420.         goto bail;
  421.     }
  422.     
  423.     //    Now, let's create the different channels.
  424.     for ( i=0; i<kMAXCHANNELS; i++ ) {
  425.         //    If the channel type exists, then create it.
  426.         if ( gSGInfo.channelType[i] != 0) {
  427.  
  428.             //    Create channel.
  429.             err = SGNewChannel((**myWindowInfo).theSG, gSGInfo.channelType[i],
  430.                                         &((**myWindowInfo).channel[i]));
  431.             if ( err != noErr ) {
  432.                 //    Fail with this channel.
  433.                 ReportWarning("\pCould not open channel: ", err);
  434.                 (**myWindowInfo).channel[i] = 0;
  435.             } else {
  436.                 //    Set the settings retrieved from preferences file.
  437.                 if ( gSGInfo.channelSettings[i] != nil ) {
  438.                     err = SGSetChannelSettings((**myWindowInfo).theSG, (**myWindowInfo).channel[i],
  439.                                             gSGInfo.channelSettings[i], 0);
  440.                     if ( err != noErr ) {
  441.                         ReportWarning("\pFailed to set channel settings: ", err);
  442.                     }
  443.                 }
  444.             }
  445.         } else
  446.             (**myWindowInfo).channel[i] = 0;
  447.     }
  448.     
  449.     //    If there is a video channel, then set the compression settings.
  450.     for ( videoChannel = -1, i=0; i<kMAXCHANNELS; i++ ) {
  451.         if ( gSGInfo.channelType[i] == VideoMediaType )
  452.             videoChannel = i;
  453.     }
  454.     if ( videoChannel >= 0 ) {
  455.         err = SGSetVideoCompressorType((**myWindowInfo).channel[videoChannel], gSGInfo.cInfo.compressorType);
  456.         if ( err != noErr ) {
  457.             ReportWarning("\pCould not set video compressor type: ", err);
  458.         }
  459.         err = SGSetVideoCompressor((**myWindowInfo).channel[videoChannel], gSGInfo.cInfo.depth, nil,
  460.                         gSGInfo.cInfo.spatialQuality, gSGInfo.cInfo.temporalQuality, gSGInfo.cInfo.keyFrameRate);
  461.         if ( err != noErr ) {
  462.             ReportWarning("\pCould not set video compressor info: ", err);
  463.         }
  464.     }
  465.     
  466.     //    Update the channels.
  467.     err = MyUpdateChannels(myWindow);
  468.     if ( err != noErr ) {
  469.         ReportWarning("\pCould not update channels: ", err);
  470.         goto bail;
  471.     }
  472.     
  473.     //    Start the preview now that everything is set up!!!
  474.     err = SGStartPreview((**myWindowInfo).theSG);
  475.     if ( err != noErr ) {
  476.         ReportWarning("\pCould not start preview.", err);
  477.         goto bail;
  478.     }
  479.     
  480.     return;
  481.  
  482. bail:
  483.     SysBeep(50);
  484.     if ( (**myWindowInfo).theSG != nil )
  485.         CloseComponent((**myWindowInfo).theSG);
  486.     if ( myWindowInfo != nil )
  487.         DisposHandle((Handle) myWindowInfo);
  488.     if ( myWindow != nil )
  489.         DisposeWindow(myWindow);
  490.     return;
  491. }
  492.  
  493. void MyClose()
  494. {
  495.     long                err;
  496.     WindowPtr            closeWindow;
  497.     WindowInfoHandle        myWindowInfo;
  498.     short                i, videoChannel;
  499.     
  500.     closeWindow = FrontWindow();
  501.     if ( closeWindow == nil )
  502.         return;
  503.     myWindowInfo = (WindowInfoHandle) GetWRefCon(closeWindow);
  504.  
  505.     //    If there is a video channel, then get the compression settings.
  506.     for ( videoChannel = -1, i=0; i<kMAXCHANNELS; i++ ) {
  507.         if ( gSGInfo.channelType[i] == VideoMediaType )
  508.             videoChannel = i;
  509.     }
  510.     if ( videoChannel >= 0 ) {
  511.         err = SGGetVideoCompressorType((**myWindowInfo).channel[videoChannel], &gSGInfo.cInfo.compressorType);
  512.         if ( err != noErr )
  513.             gSGInfo.cInfo.compressorType = 'raw ';
  514.         err = SGGetVideoCompressor((**myWindowInfo).channel[videoChannel], &gSGInfo.cInfo.depth, nil,
  515.                         &gSGInfo.cInfo.spatialQuality, &gSGInfo.cInfo.temporalQuality,
  516.                         &gSGInfo.cInfo.keyFrameRate);
  517.         if ( err != noErr ) {
  518.             gSGInfo.cInfo.depth = 16;
  519.             gSGInfo.cInfo.spatialQuality = codecLosslessQuality;
  520.             gSGInfo.cInfo.temporalQuality = 0;
  521.             gSGInfo.cInfo.keyFrameRate = 0;
  522.         }
  523.     }
  524.     
  525.     //    Get the video settings.
  526.     for ( i=0; i<kMAXCHANNELS; i++ ) {
  527.     
  528.         //    Set the video settings retrieved from preferences file.
  529.         //    *** TEMPORARY FIX BECAUSE MUSIC FAILS ON GETCHANNELSETTINGS. ***
  530.         if ( gSGInfo.channelType[i] != 0 && (**myWindowInfo).channel[i] != 0 &&
  531.                             gSGInfo.channelType[i] != 'musi') {
  532.             err = SGGetChannelSettings((**myWindowInfo).theSG, (**myWindowInfo).channel[i],
  533.                                     &(gSGInfo.channelSettings[i]), 0);
  534.             if ( err != noErr ){
  535.                 ReportWarning("\pCould not get channel settings: ", err);
  536.                 gSGInfo.channelSettings[i] = nil;
  537.             }
  538.         }
  539.     }
  540.         
  541.     //    Close the component. 
  542.     if ( (**myWindowInfo).theSG != nil )
  543.         CloseComponent((**myWindowInfo).theSG);
  544.     
  545.     if ( myWindowInfo != nil )
  546.         DisposHandle((Handle) myWindowInfo);
  547.     
  548.     DisposeWindow(closeWindow);
  549. }
  550.  
  551. /* ------------------------------------------------------------------------- */
  552.  
  553. void MySettings(short item)
  554. {
  555.     long            err;
  556.     WindowPtr        theWindow;
  557.     short            index;
  558.     
  559.     theWindow = FrontWindow();
  560.     
  561.     //    Allow only one window to be opened.
  562.     if ( theWindow != nil ) {    //    Yes, window open.
  563.         WindowInfoHandle    myWindowInfo;
  564.         
  565.         myWindowInfo = (WindowInfoHandle) GetWRefCon(theWindow);
  566.         
  567.         index = (item - 1) / 2;
  568.         if ( (item & 1) == 0 ) {
  569.             //    Pause before making changes.
  570.             err = SGPause((**myWindowInfo).theSG, true);
  571.             if ( err != noErr ) {
  572.                 ReportWarning("\pCould not pause preview: ", err);
  573.             }
  574.  
  575.             //    Disable channel.
  576.             if ( (**myWindowInfo).channel[index] != 0 ) {
  577.                 SGDisposeChannel((**myWindowInfo).theSG, (**myWindowInfo).channel[index]);
  578.                 (**myWindowInfo).channel[index] = 0;
  579.             }
  580.             
  581.             err = SGPause((**myWindowInfo).theSG, false);
  582.             if ( err != noErr ) {
  583.                 ReportWarning("\pCould not pause preview: ", err);
  584.             }
  585.  
  586.         } else {
  587.             //    Simply call SGSettingsDialog!  That simple!
  588.             SGSettingsDialog((**myWindowInfo).theSG, (**myWindowInfo).channel[index], 0, nil, DoTheRightThing, nil , 0);
  589.         }
  590.     }
  591. }
  592.  
  593. void MyResize(short item)
  594. {
  595.     WindowPtr        theWindow;
  596.     long            err;
  597.     Boolean            sizeChanged;
  598.     short            width, height;
  599.     
  600.     theWindow = FrontWindow();
  601.     
  602.     //    Allow only one window to be opened.
  603.     if ( theWindow != nil ) {    //    Yes, window open.
  604.         WindowInfoHandle    myWindowInfo;
  605.         
  606.         myWindowInfo = (WindowInfoHandle) GetWRefCon(theWindow);
  607.         sizeChanged = false;
  608.         switch ( item ) {
  609.             case 1:
  610.                 width = 160; height = 120;
  611.                 sizeChanged = true;
  612.                 break;
  613.             case 2:
  614.                 width = 240; height = 180;
  615.                 sizeChanged = true;
  616.                 break;
  617.             case 3:
  618.                 width = 320; height = 240;
  619.                 sizeChanged = true;
  620.                 break;
  621.             case 5:
  622.                 sizeChanged = GetCustomSize(&width, &height);
  623.                 break;
  624.         }
  625.         if ( sizeChanged ) {
  626.             //    Pause the sequence grabber before resizing window.
  627.             err = SGPause((**myWindowInfo).theSG, true);
  628.             if ( err != noErr ) {
  629.                 ReportWarning("\pCould not pause preview: ", err);
  630.             }
  631.             
  632.             //    Resize and then update the video channel.
  633.             SizeWindow(theWindow, width, height, false);
  634.             err = MyUpdateChannels(theWindow);
  635.             if ( err != noErr ) {
  636.                 ReportWarning("\pCould not update channels: ", err);
  637.             }
  638.             
  639.             //    OK.  We can restart again.
  640.             err = SGPause((**myWindowInfo).theSG, false);
  641.             if ( err != noErr ) {
  642.                 ReportWarning("\pCould not pause preview: ", err);
  643.             }
  644.         }
  645.     }
  646.     
  647. }
  648.  
  649. void MySpecial(short item)
  650. {
  651.     WindowPtr        theWindow;
  652.     long            err;
  653.     Boolean            updateFlag;
  654.     
  655.     theWindow = FrontWindow();
  656.     
  657.     //    Allow only one window to be opened.
  658.     if ( theWindow != nil ) {    //    Yes, window open.
  659.         WindowInfoHandle    myWindowInfo;
  660.         
  661.         myWindowInfo = (WindowInfoHandle) GetWRefCon(theWindow);
  662.         updateFlag = false;
  663.         switch ( item ) {
  664.             case kMENU_SPECIALPLAYTHRU:
  665.                 (**myWindowInfo).recordPlayThru = !(**myWindowInfo).recordPlayThru;
  666.                 updateFlag = true;
  667.                 break;
  668.             case kMENU_SPECIALSEPARATEFILES:
  669.                 (**myWindowInfo).createSeparateFiles = !(**myWindowInfo).createSeparateFiles;
  670.                 break;
  671.         }
  672.         
  673.         //    Only update if needed.
  674.         if ( updateFlag ) {
  675.             //    Pause before changes.
  676.             err = SGPause((**myWindowInfo).theSG, true);
  677.             if ( err != noErr ) {
  678.                 ReportWarning("\pCould not pause preview: ", err);
  679.             }
  680.             
  681.             //    Update the channels.
  682.             err = MyUpdateChannels(theWindow);
  683.             if ( err != noErr ) {
  684.                 ReportWarning("\pCould not update channels: ", err);
  685.             }
  686.             
  687.             //    OK to continue.
  688.             err = SGPause((**myWindowInfo).theSG, false);
  689.             if ( err != noErr ) {
  690.                 ReportWarning("\pCould not pause preview: ", err);
  691.             }
  692.         }
  693.     }
  694. }
  695.  
  696. void MyRecord()
  697. {
  698.     WindowPtr            theWindow;
  699.     long                err;
  700.     StandardFileReply    reply;
  701.     ComponentInstance    mySG;
  702.     AliasHandle            alias;
  703.     SGOutput            output;
  704.     short                i;
  705.     
  706.     theWindow = FrontWindow();
  707.     
  708.     //    Allow only one window to be opened.
  709.     if ( theWindow != nil ) {    //    Yes, window open.
  710.         WindowInfoHandle    myWindowInfo;
  711.         
  712.         myWindowInfo = (WindowInfoHandle) GetWRefCon(theWindow);
  713.         mySG = (**myWindowInfo).theSG;
  714.         if ( mySG != nil ) {
  715.             
  716.             if ( (**myWindowInfo).createSeparateFiles ) {
  717.                 for ( i=0; i<kMAXCHANNELS; i++ ) {
  718.                     if ( (**myWindowInfo).channel[i] != 0) {
  719.                         StandardPutFile("\PName of multiple file:", "\pMovie #", &reply);
  720.                         if (!reply.sfGood)
  721.                             return;
  722.                         err = CreateMovieFile(&(reply.sfFile), 'TVOD', smSystemScript,
  723.                             createMovieFileDeleteCurFile |
  724.                             createMovieFileDontCreateMovie |
  725.                             createMovieFileDontOpenFile, nil, nil);
  726.                         if ( err != noErr ) {
  727.                             ReportWarning("\pCould not create movie file 1: ", err);
  728.                             goto bail;
  729.                         }
  730.                         NewAlias(nil, &(reply.sfFile), &alias);
  731.                         if ( alias == nil )
  732.                             return;
  733.                         err = SGSetDataRef(mySG, (Handle) alias, 'alis', seqGrabToDisk);
  734.                         if ( err != noErr ) {
  735.                             ReportWarning("\pCould not set movie resource output: ", err);
  736.                             goto bail;
  737.                         }
  738.                         err = SGNewOutput(mySG, (Handle) alias, 'alis', seqGrabToDisk, &output);
  739.                         if ( err != noErr ) {
  740.                             ReportWarning("\pCould not create data output1: ", err);
  741.                             goto bail;
  742.                         }
  743.                         err = SGSetChannelOutput(mySG, (**myWindowInfo).channel[i], output);
  744.                         if ( err != noErr ) {
  745.                             ReportWarning("\pCould not set video channel output: ", err);
  746.                             goto bail;
  747.                         }
  748.                     }
  749.                 }
  750.             } else {
  751.                 //    If creating single file, then do this.
  752.                 StandardPutFile("\PName of new movie:", "\pMovie", &reply);
  753.                 if (!reply.sfGood)
  754.                     return;
  755.                 err = SGSetDataOutput(mySG, &reply.sfFile, seqGrabToDisk);
  756.                 if ( err != noErr ) {
  757.                     ReportWarning("\pCould not set data output: ", err);
  758.                     goto bail;
  759.                 }
  760.             }
  761.  
  762.             //    Set the window title so that the user knows that we are recording.
  763.             SetWTitle(theWindow, "\pRecording... click mouse to stop.");
  764.  
  765.             //    Start recording.
  766.             err = SGStartRecord(mySG);
  767.             if ( err != noErr ) {
  768.                 ReportWarning("\pCould not start recording.  The following error was returned: ", err);
  769.             }
  770.             
  771.             //    Keep recording until the mouse button is pressed.
  772.             while (!Button() && !err) {
  773.                 err = SGIdle(mySG);
  774.             }
  775.             
  776.             //    Stop recording.
  777.             err = SGStop(mySG);
  778.             if ( err != noErr ) {
  779.                 ReportWarning("\pCould not stop sequence grabber: ", err);
  780.                 goto bail;
  781.             } else
  782.                 SetWTitle(theWindow, "\pMovie captured.");
  783.  
  784.             //    Start preview again.
  785.  
  786.     err = MyUpdateChannels(theWindow);
  787.     if ( err != noErr ) {
  788.         ReportWarning("\pCould not update channels: ", err);
  789.         goto bail;
  790.     }
  791.     
  792.             err = SGStartPreview((**myWindowInfo).theSG);
  793.             if ( err != noErr ) {
  794.                 ReportWarning("\pCould not start preview: ", err);
  795.                 goto bail;
  796.             }
  797.             
  798.             //    Reset the window title.
  799.             SetWTitle(theWindow, "\pCapture window");
  800.  
  801.             FlushEvents(mDownMask | mUpMask, 0);
  802.         }
  803.     }
  804.     
  805. bail:
  806.     return;
  807. }
  808.  
  809. void MyDrag(WindowPtr theWindow, Point where)
  810. {
  811.     long            err;
  812.  
  813.     //    Allow only one window to be opened.
  814.     if ( theWindow != nil ) {    //    Yes, window open.
  815.         WindowInfoHandle    myWindowInfo;
  816.         
  817.         myWindowInfo = (WindowInfoHandle) GetWRefCon(theWindow);
  818.         if ((**myWindowInfo).theSG != nil)
  819.             //    Pause preview.
  820.             err = SGPause((**myWindowInfo).theSG, true);
  821.             if ( err != noErr ) {
  822.                 ReportWarning("\pCould no pause preview: ", err);
  823.             }
  824.             
  825.             //    Drag window.
  826.             DragWindow (theWindow, where, &qd.screenBits.bounds);
  827.             
  828.             //    OK to restart preview.
  829.             err = SGPause((**myWindowInfo).theSG, false);
  830.             if ( err != noErr ) {
  831.                 ReportWarning("\pCould not pause preview: ", err);
  832.             }
  833.     }
  834. }
  835.  
  836. void MyUpdate(WindowPtr theWindow)
  837. {
  838.     long            err;
  839.  
  840.     //    Allow only one window to be opened.
  841.     if ( theWindow != nil ) {    //    Yes, window open.
  842.         WindowInfoHandle    myWindowInfo;
  843.         
  844.         myWindowInfo = (WindowInfoHandle) GetWRefCon(theWindow);
  845.         if ((**myWindowInfo).theSG != nil)
  846.             //    Pause and continue to reset clip.
  847.             err = SGPause((**myWindowInfo).theSG, true);
  848.             if ( err != noErr ) {
  849.                 ReportWarning("\pCould not pause preview: ", err);
  850.             }
  851.             err = SGPause((**myWindowInfo).theSG, false);
  852.             if ( err != noErr ) {
  853.                 ReportWarning("\pCould not pause preview: ", err);
  854.             }
  855.     }
  856. }
  857.  
  858. long MyUpdateChannels(WindowPtr theWindow)
  859. {
  860.     long                err;
  861.     WindowInfoHandle    myWindowInfo;
  862.     long                usage;
  863.     short                i, videoChannel;
  864.     err = noErr;
  865.     myWindowInfo = (WindowInfoHandle) GetWRefCon(theWindow);
  866.     
  867.     //    Update the video channel if it exists.
  868.     for ( videoChannel = -1, i=0; i<kMAXCHANNELS; i++ ) {
  869.         if ( gSGInfo.channelType[i] == VideoMediaType )
  870.             videoChannel = i;
  871.     }
  872.     if ( videoChannel >= 0 ) {
  873.         //    Set the bounds to the entire portRect.
  874.         err = SGSetChannelBounds((**myWindowInfo).channel[videoChannel], &(theWindow->portRect));
  875.         if ( err != noErr )
  876.             goto bail;
  877.             
  878.         //    Set the video usage depending on whether or not there is playthru.
  879.         usage = seqGrabPreview | seqGrabRecord;
  880.         if ( !((**myWindowInfo).recordPlayThru) )
  881.             usage |= seqGrabPlayDuringRecord;
  882.         err = SGSetChannelUsage((**myWindowInfo).channel[videoChannel], usage);
  883.         if ( err != noErr )
  884.             goto bail;
  885.     }
  886.  
  887.     for ( i=0; i<kMAXCHANNELS; i++ ) {
  888.     //    Since sound may be turned off, check before setting sound usage.
  889.         if ( (gSGInfo.channelType[i] != VideoMediaType && gSGInfo.channelType[i] != 0) &&
  890.                 (**myWindowInfo).channel[i] != 0) {
  891.             err = SGSetChannelUsage((**myWindowInfo).channel[i], seqGrabPreview | seqGrabRecord |  seqGrabPlayDuringRecord);
  892.             if ( err != noErr )
  893.                 goto bail;
  894.         }
  895.     }
  896.     
  897. bail:
  898.     return ( err );
  899. }
  900.  
  901. /* ------------------------------------------------------------------------- */
  902.  
  903. Boolean GetCustomSize(short *width, short *height)
  904. {
  905.     GrafPtr        savePort;
  906.     GDHandle    saveGD;
  907.     DialogPtr    theDialog;
  908.     short        itemHit;
  909.     Str255        myStr;
  910.     Boolean        done, ret;
  911.     long        lWidth, lHeight;
  912.     
  913.     GetPort(&savePort);
  914.     saveGD = GetGDevice();
  915.     theDialog = GetNewDialog(130, nil, (WindowPtr) -1);
  916.     SetPort(theDialog);
  917.     SetGDevice(GetMainDevice());
  918.     
  919.     //    Reset data to begin.
  920.     SetText(theDialog, 4, "\p640");
  921.     SetText(theDialog, 6, "\p480");
  922.  
  923.     //    Get membershipid and each inventory id
  924.     done = false;
  925.     do {
  926.         ModalDialog(nil, &itemHit);
  927.         GetText(theDialog, 4, myStr);
  928.         StringToNum(myStr, &lWidth);
  929.         GetText(theDialog, 6, myStr);
  930.         StringToNum(myStr, &lHeight);
  931.         if (itemHit == 1 ) {
  932.             if (lWidth > 0 && lWidth <= 640 && lHeight >= 0 && lHeight <= 480)
  933.                 done = true;
  934.             else
  935.                 SysBeep(50);
  936.         }
  937.     } while ((!done) && (itemHit != 2));
  938.  
  939.     if ( itemHit == 1 ) {
  940.         GetText(theDialog, 4, myStr);
  941.         StringToNum(myStr, &lWidth);
  942.         *width = lWidth;
  943.         GetText(theDialog, 6, myStr);
  944.         StringToNum(myStr, &lHeight);
  945.         *height = lHeight;
  946.         ret = true;
  947.     } else {
  948.         ret = false;
  949.     }
  950.  
  951.     DisposeDialog(theDialog);
  952.     SetPort(savePort);
  953.     SetGDevice(saveGD);
  954.     
  955.     return ( ret );
  956. }
  957.  
  958. /* ------------------------------------------------------------------------- */
  959.  
  960. void GetText(DialogPtr theDialog, short item, Str255 myStr)
  961. {
  962.     Handle        myHandle;
  963.     Rect        myRect;
  964.     short        myType;
  965.  
  966.     GetDItem(theDialog, item, &myType, &myHandle, &myRect);
  967.     GetIText(myHandle, myStr);
  968. }
  969.  
  970. void SetText(DialogPtr theDialog, short item, Str255 myStr)
  971. {
  972.     Handle        myHandle;
  973.     Rect        myRect;
  974.     short        myType;
  975.  
  976.     GetDItem(theDialog, item, &myType, &myHandle, &myRect);
  977.     SetIText(myHandle, myStr);
  978. }
  979.  
  980.